#pragma once

#define UAEMAJOR 2
#define UAEMINOR 3
#define UAESUBREV 3

#define GFX_WINDOW 0
#define GFX_FULLSCREEN 1
#define GFX_FULLWINDOW 2

#define MAX_TOTAL_SCSI_DEVICES 8

//  maximum number native input devices supported (single type)
#define MAX_INPUT_DEVICES 8

//  maximum number of native input device's buttons and axles supported
#define MAX_INPUT_DEVICE_EVENTS 256

//  4 different customization settings
#define MAX_INPUT_SETTINGS 4

//  last slot is for gameport panel mappings
#define GAMEPORT_INPUT_SETTINGS 3

#define MAX_INPUT_SUB_EVENT 4
#define MAX_INPUT_SUB_EVENT_ALL 5
#define SPARE_SUB_EVENT 4

#define MAX_JPORTS 4
#define NORMAL_JPORTS 2

#define JPORT_NONE -1
#define JPORT_CUSTOM -2
#define JPORT_AF_NORMAL 1
#define JPORT_AF_TOGGLE 2
#define JPORT_AF_ALWAYS 3

#define MAX_SPARE_DRIVES 20

#define MOUNT_CONFIG_SIZE 30

#define MAX_PATHS 8

struct multipath
{
    CString path[MAX_PATHS];
};

enum KbdLang
{
    KBD_LANG_US,
    KBD_LANG_DK,
    KBD_LANG_DE,
    KBD_LANG_SE,
    KBD_LANG_FR,
    KBD_LANG_IT,
    KBD_LANG_ES
};

enum CDSlotType
{
    cdslottype_Disabled= -1,
    cdslottype_Default= 0,
    cdslottype_Image= 1,
    cdslottype_IOCTL= 2,
    cdslottype_SPTI= 3,
    cdslottype_ASPI= 4
};

struct CDSlot
{
    CString name;
    bool inuse;
    bool delayed;
    CDSlotType type;

    CDSlot ()
    {
        inuse = false;
        delayed = 0;
        type = cdslottype_Default;
    }

    bool operator != (const CDSlot& right) const
    {
        return !operator == (right);
    }

    bool operator == (const CDSlot& right) const
    {
        return (name == right.name) &&
               (inuse == right.inuse) &&
               (delayed == right.delayed) &&
               (type == right.type);
    }
};

struct UaeInputDevice
{
    CString name;
    CString configname;
    short eventid[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL];
    CString custom[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL];
    ushort flags[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL];
    sbyte port[MAX_INPUT_DEVICE_EVENTS][MAX_INPUT_SUB_EVENT_ALL];
    short extra[MAX_INPUT_DEVICE_EVENTS];
    sbyte enabled;

    UaeInputDevice ()
    {
        enabled = 0;

        for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++)
        {
            extra[i] = 0;

            for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++)
            {
                eventid[i][j] = 0;
                flags[i][j] = 0;
                port[i][j] = 0;
            }
        }
    }

    void clear()
    {
        *this = UaeInputDevice();
    }

    void clear_state()
    {
        CString n = name;
        CString c = configname;
        clear();
        name = n;
        configname = c;
    }

    bool operator != (const UaeInputDevice& right) const
    {
        return !operator == (right);
    }

    bool operator == (const UaeInputDevice& right) const
    {
        if (name != right.name)
            return false;
        if (configname != right.configname)
            return false;
        if (enabled != right.enabled)
            return false;

        for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++)
        {
            if (extra[i] != right.extra[i])
                return false;

            for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++)
            {
                if (eventid[i][j] != right.eventid[i][j])
                    return false;
                if (custom[i][j] != right.custom[i][j])
                    return false;
                if (flags[i][j] != right.flags[i][j])
                    return false;
                if (port[i][j] != right.port[i][j])
                    return false;
            }
        }

        return true;
    }
};

struct JPort
{
    int id;
    int mode;
    int autofire;
    CString name;
    CString configname;

    JPort ()
    {
        id = 0;
        mode = 0;
        autofire = 0;
    }

    void clear()
    {
        *this = JPort();
    }

    bool operator != (const JPort& right) const
    {
        return !operator == (right);
    }

    bool operator == (const JPort& right) const
    {
        return (id == right.id) &&
               (mode == right.mode) &&
               (autofire == right.autofire);
        (name == right.name) &&
        (configname == right.configname);
    }
};

struct FloppySlot
{
    CString df;
    int dfxtype;
    CString floppy_sounds;

    FloppySlot ()
    {
        dfxtype = 0;
    }

    void clear()
    {
        *this = FloppySlot();
    }

    bool operator != (const FloppySlot& right) const
    {
        return !operator == (right);
    }

    bool operator == (const FloppySlot& right) const
    {
        return (df == right.df) &&
               (dfxtype == right.dfxtype) &&
               (floppy_sounds == right.floppy_sounds);
    }
};

struct wh
{
    int x;
    int y;
    int width;
    int height;

    bool operator != (const wh& right) const
    {
        return !operator == (right);
    }

    bool operator == (const wh& right) const
    {
        return (x == right.x) &&
               (y == right.y) &&
               (width == right.width) &&
               (height == right.height);
    }
};

struct DeviceConfigInfo
{
    CString device_name;
    CString volume_name;
    CString rootdir;
    bool ishdf;
    bool readonly;
    int bootpri;
    bool autoboot;
    bool donotmount;
    CString file_sys;
    int surfaces;
    int sectors;
    int reserved;
    int blocksize;
    int configoffset;
    int controller;

    DeviceConfigInfo ()
    {
        ishdf = false;
        readonly = false;
        autoboot = false;
        donotmount = false;
        bootpri = 0;
        surfaces = 0;
        sectors = 0;
        reserved = 0;
        blocksize = 0;
        configoffset = 0;
        controller = 0;
    }

    bool operator != (const DeviceConfigInfo& right) const
    {
        return !operator == (right);
    }

    bool operator == (const DeviceConfigInfo& right) const
    {
        return (ishdf == right.ishdf) &&
               (readonly == right.readonly) &&
               (autoboot == right.autoboot) &&
               (donotmount == right.donotmount) &&
               (bootpri == right.bootpri) &&
               (surfaces == right.surfaces) &&
               (sectors == right.sectors) &&
               (reserved == right.reserved) &&
               (blocksize == right.blocksize) &&
               (configoffset == right.configoffset) &&
               (controller == right.controller);
    }
};

#define MAX_CHIPSET_REFRESH 10
#define MAX_CHIPSET_REFRESH_TOTAL (MAX_CHIPSET_REFRESH + 2)
#define CHIPSET_REFRESH_PAL (MAX_CHIPSET_REFRESH + 0)
#define CHIPSET_REFRESH_NTSC (MAX_CHIPSET_REFRESH + 1)

struct ChipsetRefresh
{
    bool locked;
    bool rtg;
    int horiz;
    int vert;
    int lace;
    int ntsc;
    int vsync;
    int framelength;
    double rate;
    CString label;
    CString commands;

    ChipsetRefresh()
    {
        locked = false;
        rtg = false;
        horiz = 0;
        vert = 0;
        lace = 0;
        ntsc = 0;
        vsync = 0;
        framelength = 0;
        rate = 0;
    }

    bool operator != (const ChipsetRefresh& right) const
    {
        return !operator == (right);
    }

    bool operator == (const ChipsetRefresh& right) const
    {
        return (locked == right.locked) &&
               (rtg == right.rtg) &&
               (horiz == right.horiz) &&
               (vert == right.vert) &&
               (lace == right.lace) &&
               (ntsc == right.ntsc) &&
               (vsync == right.vsync) &&
               (framelength == right.framelength) &&
               (rate == right.rate) &&
               (label == right.label) &&
               (commands == right.commands);
    }
};

struct CConfiguration
{
    CConfiguration();

    void clear();
    void setfloppycount(int a_count, int a_dfxtype = 0 /*DRV_35_DD*/);

    bool operator != (const CConfiguration& right) const;
    bool operator == (const CConfiguration& right) const;

    CString Description;
    CString AdditionalInformation;

    int Version;

    CString config_hardware_path;
    CString config_host_path;
    // TCHAR config_window_title[256];

    bool use_serial;
    bool serial_demand;
    bool serial_hwctsrts;
    bool serial_direct;
    int serial_stopbits;
    int parallel_matrix_emulation;
    bool parallel_postscript_emulation;
    bool parallel_postscript_detection;
    int parallel_autoflush_time;
    CString ghostscript_parameters;
    bool socket_emu;

    KbdLang keyboard_lang;

    bool sound_produce;
    int sound_maxbsiz;

    //  SOUND_INTERPOLATION_NONE 0
    //  SOUND_INTERPOLATION_ANTI 1
    //  SOUND_INTERPOLATION_SINC 2
    //  SOUND_INTERPOLATION_RH 3
    //  SOUND_INTERPOLATION_CRUX 4
    int sound_interpol;

    //  FILTER_SOUND_OFF 0
    //  FILTER_SOUND_LED_EMUL 1
    //  FILTER_SOUND_LED_ON 2
    //  FILTER_SOUND_LED_OFF 3
    int sound_filter;

    //  FILTER_SOUND_TYPE_A500 0
    //  FILTER_SOUND_TYPE_A1200 1
    int sound_filter_type;

    int sound_volume;
    int sound_volume_cd;

    bool jit_no_flags;
    bool jit_fpu;
    bool jit_fpu_more_compatible;
    bool jit_hard_flush;
    bool jit_const_jump;
    int jit_cache_size;
    int jit_optcount[10];

    int gfx_display;
    CString gfx_display_name;
    int gfx_framerate;
    wh gfx_size_win;
    wh gfx_size_fs;
    wh gfx_size;
    bool gfx_scandoubler;
    int gfx_refreshrate;
    int gfx_avsync;
    int gfx_pvsync;
    int gfx_avsyncmode;
    int gfx_pvsyncmode;
    int gfx_resolution;
    int gfx_vresolution;
    int gfx_lores_mode;
    int gfx_scanlines;
    int gfx_afullscreen;
    int gfx_pfullscreen;
    int gfx_xcenter;
    int gfx_ycenter;
    int gfx_luminance;
    int gfx_contrast;
    int gfx_gamma;
    bool gfx_blackerthanblack;
    int gfx_backbuffers;
    int gfx_color_mode;

    int gfx_filter;
    CString gfx_filtershader;
    int gfx_filter_zoom_mult;
    int gfx_filter_keep_aspect;
    int gfx_filter_aspect;
    int gfx_filter_autoscale;

    bool immediate_blits;
    bool waiting_blits;
    uint chipset_mask;
    bool ntscmode;
    bool genlock;
    double chipset_refreshrate;
    ChipsetRefresh cr[MAX_CHIPSET_REFRESH + 2];
    int cr_selected;
    int collision_level;
    int leds_on_screen;
    wh osd_pos;
    int keyboard_leds[3];
    bool keyboard_leds_in_use;
    int scsi;
    bool sana2;
    bool uaeserial;
    int cpu_idle;
    bool cpu_cycle_exact;
    int cpu_clock_multiplier;
    int cpu_frequency;
    bool blitter_cycle_exact;
    int floppy_speed;
    int floppy_write_length;
    int floppy_random_bits_min;
    int floppy_random_bits_max;
    bool tod_hack;
    int turbo_emulation;

    int cs_compatible;
    int cs_ciaatod;
    int cs_rtc;
    bool cs_ksmirror_e0;
    bool cs_ksmirror_a8;
    bool cs_ciaoverlay;
    bool cs_cd32cd;
    bool cs_cd32c2p;
    bool cs_cd32nvram;
    bool cs_cdtvcd;
    bool cs_cdtvram;
    int cs_cdtvcard;
    int cs_ide;
    bool cs_pcmcia;
    bool cs_a1000ram;
    int cs_fatgaryrev;
    int cs_ramseyrev;
    int cs_mbdmac;
    bool cs_cdtvscsi;
    bool cs_a2091;
    bool cs_a4091;
    bool cs_df0idhw;
    bool cs_slowmemisfast;
    bool cs_resetwarning;
    bool cs_denisenoehb;
    bool cs_dipagnus;
    bool cs_agnusbltbusybug;

    CString romfile;
    CString romextfile;
    CString flashfile;
    CString cartfile;
    int cart_internal;
    CString prtname;
    CString sername;
    CString a2065name;

    CDSlot cdslots[MAX_TOTAL_SCSI_DEVICES];

    CString inprecfile;
    bool inprec_autoplay;

    int m68k_speed;
    int cpu_model;
    int mmu_model;
    int cpu060_revision;
    int fpu_model;
    int fpu_revision;
    bool cpu_compatible;
    bool address_space_24;

    bool picasso96_nocustom;
    int picasso96_modeflags;

    uint z3fastmem_size;
    uint fastmem_size;
    uint chipmem_size;
    uint slowmem_size;
    uint mbresmem_low_size;
    uint mbresmem_high_size;
    uint gfx_mem_size;

    bool filesys_no_uaefsdb;
    bool filesys_custom_uaefsdb;
    int uae_hide;

    int mountitems;
    DeviceConfigInfo mounted_devices[MOUNT_CONFIG_SIZE];

    FloppySlot floppies[4];
    CString dfxlist[MAX_SPARE_DRIVES];

    int floppy_sound_volume;

    bool win32_middle_mouse;
    bool win32_logfile;
    bool win32_alwaysontop;
    bool win32_powersavedisabled;
    bool win32_minimize_inactive;
    int win32_statusbar;

    int win32_active_priority;
    int win32_inactive_priority;
    bool win32_inactive_pause;
    bool win32_inactive_nosound;
    int win32_iconified_priority;
    bool win32_iconified_pause;
    bool win32_iconified_nosound;

    bool win32_rtgmatchdepth;
    bool win32_rtgscaleifsmall;
    bool win32_rtgallowscaling;
    int win32_rtgscaleaspectratio;
    int win32_rtgvblankrate;
    bool win32_borderless;
    bool win32_ctrl_F11_is_quit;
    bool win32_automount_removable;
    bool win32_automount_drives;
    bool win32_automount_cddrives;
    bool win32_automount_netdrives;
    bool win32_automount_removabledrives;
    int win32_midioutdev;
    int win32_midiindev;
    int win32_uaescsimode;
    int win32_samplersoundcard;
    bool win32_norecyclebin;
    int win32_specialkey;
    int win32_guikey;
    int win32_kbledmode;

    int statecapturerate;
    int statecapturebuffersize;

    int input_selected_setting;
    int input_joymouse_multiplier;
    int input_joymouse_deadzone;
    int input_joystick_deadzone;
    int input_joymouse_speed;
    int input_analog_joystick_mult;
    int input_analog_joystick_offset;
    int input_autofire_linecnt;
    int input_mouse_speed;
    bool input_virtual_mouse;
    bool input_magic_mouse;
    int input_magic_mouse_cursor;

    JPort jports[MAX_JPORTS];

    UaeInputDevice joystick_settings[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES];
    UaeInputDevice mouse_settings[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES];
    UaeInputDevice keyboard_settings[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES];

    int dongle;
    int input_contact_bounce;
};

extern bool record_sound;

extern CConfiguration g_curr_conf;
extern CConfiguration g_changed_conf;
extern CConfiguration g_work_conf;